package cn.snmp.mutual.org.opennms.protocols.ip;

import java.io.*;
import java.util.*;
import java.net.*;

public class IPv4Address implements Serializable {
    static final long serialVersionUID = 1946711645921732057L;
    private byte[] m_addr;

    private byte[] dup(final byte[] src) {
        byte[] cpy = null;
        if (src != null) {
            cpy = new byte[src.length];
            for (int x = 0; x < src.length; ++x) {
                cpy[x] = src[x];
            }
        }
        return cpy;
    }

    private static int byteToInt(final byte b) {
        int r = b;
        if (r < 0) {
            r += 256;
        }
        return r;
    }

    public static String addressToString(final int ipv4Addr) {
        final StringBuffer buf = new StringBuffer();
        buf.append(ipv4Addr >> 24 & 0xFF);
        buf.append('.');
        buf.append(ipv4Addr >> 16 & 0xFF);
        buf.append('.');
        buf.append(ipv4Addr >> 8 & 0xFF);
        buf.append('.');
        buf.append(ipv4Addr & 0xFF);
        return buf.toString();
    }

    public static String addressToString(final byte[] buf) {
        if (buf.length != 4) {
            throw new IllegalArgumentException("IPv4 Address must be 4-bytes in length");
        }
        final int a = byteToInt(buf[0]);
        final int b = byteToInt(buf[1]);
        final int c = byteToInt(buf[2]);
        final int d = byteToInt(buf[3]);
        final StringBuffer sbuf = new StringBuffer();
        sbuf.append(a).append('.').append(b).append('.').append(c).append('.').append(d);
        return sbuf.toString();
    }

    public IPv4Address() {
        (this.m_addr = new byte[4])[0] = 0;
        this.m_addr[1] = 0;
        this.m_addr[2] = 0;
        this.m_addr[3] = 0;
    }

    public IPv4Address(final IPv4Address second) {
        this.m_addr = this.dup(second.m_addr);
    }

    public IPv4Address(final byte[] addr) {
        if (addr.length != 4) {
            throw new IllegalArgumentException("Invalid address length");
        }
        this.m_addr = this.dup(addr);
    }

    public IPv4Address(final int ipv4Addr) {
        (this.m_addr = new byte[4])[0] = (byte) (ipv4Addr >>> 24);
        this.m_addr[1] = (byte) (ipv4Addr >> 16 & 0xFF);
        this.m_addr[2] = (byte) (ipv4Addr >> 8 & 0xFF);
        this.m_addr[3] = (byte) (ipv4Addr & 0xFF);
    }

    public IPv4Address(final String ipv4Addr) {
        final StringTokenizer tok = new StringTokenizer(ipv4Addr, ".");
        if (tok.countTokens() != 4) {
            throw new IllegalArgumentException("Invalid Dotted Decimal IPv4 Address");
        }
        this.m_addr = new byte[4];
        for (int x = 0; x < 4; ++x) {
            final int converted = Integer.parseInt(tok.nextToken());
            if (converted < 0 || converted > 255) {
                throw new IllegalArgumentException("Invalid IPv4 Address string");
            }
            this.m_addr[x] = (byte) (converted & 0xFF);
        }
    }

    public IPv4Address(final InetAddress addr) {
        this.m_addr = this.dup(addr.getAddress());
    }

    public int getAddress() {
        int addr = byteToInt(this.m_addr[0]) << 24;
        addr |= byteToInt(this.m_addr[1]) << 16;
        addr |= byteToInt(this.m_addr[2]) << 8;
        addr |= byteToInt(this.m_addr[3]);
        return addr;
    }

    public void setAddress(final IPv4Address second) {
        this.m_addr = this.dup(second.m_addr);
    }

    public void setAddress(final byte[] addr) {
        if (addr.length != 4) {
            throw new IllegalArgumentException("Invalid address length");
        }
        this.m_addr = this.dup(addr);
    }

    public void setAddress(final int ipv4Addr) {
        (this.m_addr = new byte[4])[0] = (byte) (ipv4Addr >>> 24);
        this.m_addr[1] = (byte) (ipv4Addr >> 16 & 0xFF);
        this.m_addr[2] = (byte) (ipv4Addr >> 8 & 0xFF);
        this.m_addr[3] = (byte) (ipv4Addr & 0xFF);
    }

    public void setAddress(final String ipv4Addr) {
        final StringTokenizer tok = new StringTokenizer(ipv4Addr, ".");
        if (tok.countTokens() != 4) {
            throw new IllegalArgumentException("Invalid Dotted Decimal IPv4 Address");
        }
        this.m_addr = new byte[4];
        for (int x = 0; x < 4; ++x) {
            final int converted = Integer.parseInt(tok.nextToken());
            if (converted < 0 || converted > 255) {
                throw new IllegalArgumentException("Invalid IPv4 Address string");
            }
            this.m_addr[x] = (byte) (converted & 0xFF);
        }
    }

    public void setAddress(final InetAddress addr) {
        this.m_addr = this.dup(addr.getAddress());
    }

    @Override
    public boolean equals(final Object obj) {
        boolean bRC = false;
        if (obj instanceof IPv4Address) {
            final byte[] t = ((IPv4Address) obj).m_addr;
            bRC = true;
            for (int x = 0; x < 4; ++x) {
                if (this.m_addr[x] != t[x]) {
                    bRC = false;
                }
            }
        } else if (obj instanceof Integer) {
            if ((int) obj == this.getAddress()) {
                bRC = true;
            }
        } else if (obj instanceof String) {
            try {
                final IPv4Address addr = new IPv4Address((String) obj);
                bRC = this.equals(addr);
            } catch (IllegalArgumentException e) {
                bRC = false;
            }
        }
        return bRC;
    }

    @Override
    public String toString() {
        return addressToString(this.m_addr);
    }
}
